package com.appspot.autopartymanager.xml;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public final class DomUtils {
    private static Logger logger = LoggerFactory.getLogger(DomUtils.class);

    private DomUtils() {
    }

    public static <T> void bind(T bean, NodeList attributes) {
        for (Field field : bean.getClass().getDeclaredFields()) {
            NodeAttribute annotation = field.getAnnotation(NodeAttribute.class);
            if (annotation != null) {
                bind(bean, attributes, ((NodeAttribute) annotation), field);
            }
        }
        for (Method method : bean.getClass().getDeclaredMethods()) {
            NodeAttribute annotation = method.getAnnotation(NodeAttribute.class);
            if (annotation != null) {
                bind(bean, attributes, ((NodeAttribute) annotation), method);
            }
        }
    }

    private static <T> void bind(T bean, NodeList attributes,
            NodeAttribute nodeAttribute, Method method) {
        String fieldName = null;
        if (method.getName().startsWith("set")) {
            char[] cArr = method.getName().toCharArray();
            StringBuilder sb = new StringBuilder(cArr.length - 3);
            sb.append(Character.toLowerCase(cArr[3]));
            for (int i = 4; i < cArr.length; i++) {
                sb.append(cArr[i]);
            }
            fieldName = sb.toString();
        }
        String name = "".equals(nodeAttribute.name()) ? fieldName : nodeAttribute.name();
        bind(bean, attributes, name, fieldName);
    }

    private static <T> void bind(T bean, NodeList attributes,
            NodeAttribute nodeAttribute, Field field) {
        String name = "".equals(nodeAttribute.name()) ? field.getName() : nodeAttribute.name();
        bind(bean, attributes, name, field.getName());
    }
    
    private static <T> void bind(T bean, NodeList attributes, String name, String fieldName) {
        Node attribute = null;
        for (int i = 0, l = attributes.getLength(); i < l; i++) {
            attribute = attributes.item(i);
            if (name.equals(attribute.getNodeName())) {
                try {
                    BeanUtils.setProperty(
                        bean,
                        fieldName,
                        attribute.getTextContent());
                } catch (Exception e) {
                    logger.error("Could not set property.", e);
                }
            }
        }
    }
}